package com.springboot.codeminestarter.codemine.business.user.service;

import com.springboot.codeminestarter.codemine.base.jwt.JWToken;
import com.springboot.codeminestarter.codemine.business.user.controller.LoginUserController;
import com.springboot.codeminestarter.codemine.business.user.dao.LoginUserDao;
import com.springboot.codeminestarter.codemine.business.user.domain.LoginUser;
import com.springboot.codeminestarter.codemine.constant.Constant;
import com.springboot.codeminestarter.codemine.exception.BusinessException;
import com.springboot.codeminestarter.codemine.tips.TipKey;
import com.springboot.codeminestarter.codemine.tips.TipMess;
import com.springboot.codeminestarter.codemine.utils.*;
import com.springboot.codeminestarter.codemine.wrapper.RedisWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class LoginUserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginUserController.class);

    private AtomicInteger visits = new AtomicInteger(1);

    @Resource
    private LoginUserDao userDao;

    @Resource
    private RedisWrapper redisWrapper;

    /**
     * 获取登录对象
     */
    public LoginUser getLoginUser(String userId) {

        // 10s内不允许再次访问
/*        Boolean flag = redisWrapper.putIfAbsentWithExpireTime(TipKey.REDIS_NOT_PERMIT_ACCESS_AGAIN, "getLoginUser", 10, TimeUnit.SECONDS);
        if (!flag) {
            throw new BusinessException(TipMess.USER_NOT_PERMIT_ACCESS_AGAIN);
        }*/

        // 30s内不允许访问超过三次
        Boolean getLoginUser = redisWrapper.putIfAbsentWithExpireTime(TipKey.REDIS_NOT_PERMIT_ACCESS_OVER_3, "getLoginUser", 30, TimeUnit.SECONDS);
        /*if (getLoginUser) {
            this.visits.set(1);
        } else {
            int visits = this.visits.incrementAndGet();
            if (visits > 3) {
                throw new BusinessException(TipMess.USER_NOT_PERMIT_ACCESS_OVER_3);
            }
        }*/

        return userDao.getLoginUser(userId);
    }

    /**
     * 用户注册
     * 处理并发问题: 1.数据库唯一索引
     *             2.悲观锁实现
     */
    @Transactional(rollbackFor = Exception.class)
    public void registerLoginUser(LoginUser user) {

        synchronized (LoginUserService.class) {
            List<LoginUser> userList = userDao.getLoginUserByUsername(user.getUsername());
            if (userList.size() > 0) {
                throw new BusinessException(TipMess.USER_REGISTER_USERNAME_REPEAT);
            }
            user.setId(UUIDUtil.uuid());
            user.setPassword(Md5Util.MD5Wrapper(user.getPassword()));
            userDao.registerLoginUser(user);
        }
    }

    /**
     * 用户登录
     */
    @Transactional(rollbackFor = Exception.class)
    public LoginUser loginUser(LoginUser registerUser) {

        LoginUser loginUser = userDao.loginUser(registerUser);
        if (Objects.isNull(loginUser)) {
            throw new BusinessException(TipMess.USER_NOT_FOUND_USER);
        }

        String dateTime = DateUtil.getDateTime();
        String expireTime = DateUtil.getExpireTime(Constant.EXPIRE_TIME_HOUR);

        // create token
        registerUser.setCreateTime(DateUtil.getDateTime());
        registerUser.setExpireTime(expireTime);
        String token = JWToken.generateJwtToken(registerUser);

        // record token
        loginUser.setToken(token);
        loginUser.setExpireTime(expireTime);
        loginUser.setLoginTime(dateTime);
        loginUser.setUpdateTime(dateTime);
        userDao.updateLoginUser(loginUser);

        redisWrapper.putValueWithExpireTime(loginUser.getUserId(), loginUser, Constant.EXPIRE_TIME_HOUR, TimeUnit.HOURS);
        return loginUser;
    }

    /**
     * 用户注销
     */
    public Boolean logoutUser(String userId) {

        return redisWrapper.delWithKey(userId);
    }
}
